home *** CD-ROM | disk | FTP | other *** search
/ APDL Other Worlds / APDL Other Worlds Collection.iso / SF3000 / Extras / CBlibrary / c / err < prev    next >
Encoding:
Text File  |  2003-10-16  |  8.2 KB  |  266 lines

  1. /*
  2.  * CBLibrary - err
  3.  * Copyright (C) 2003  Chris Bazley
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2.1 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19.  
  20. /* Original version by Tony Houghton for !FormText
  21.  07.05.01 CJB - records errors for SFtoSpr
  22.  08.06.01 CJB - error block made global to save space
  23.  03.07.01 CJB - needs messages "IntErr1", "IntErr2"
  24.  25.07.01 CJB - considerable optimisation of fancy message construction
  25.               - uses RISC OS 3.5 extensions
  26.               - No longer tries to prepend "Internal Error" (pretentious)
  27.  04.10.01 CJB - removed strncpycr() 'cos saw no real need for it
  28.               - made various variables static and publicised others
  29.  12.12.01 CJB - Removed calls to msgs_lookup() to prevent re-entrancy 
  30.                 via err_check()
  31.               - Failure to find message tokens is now fatal error reported in 
  32.                 simplest possible manner.
  33.  14.12.01 CJB - Functions that construct errors now use a local erblk
  34.  25.05.02 CJB - Added signal handler and separate fancy fatal error message.
  35.  13.11.02 CJB - Separate signal handler for SIGSTAK that uses static error 
  36.                 message and doesn't perform stack limit checking
  37.  14.11.02 CJB - Removed signal handlers, since new C Library does a better job.
  38.  27.04.03 CJB - erblk was unnecessarily being inited twice in err_complain().
  39.                 No return from err_box_die().
  40.                 err_box_continue() only returns if 'Continue' selected .
  41.                 A tiddly bit smaller.
  42.  05.08.03 CJB - eliminated strcpy(x, "") in favour of fast x[0] = '/0';
  43. */
  44.  
  45. #include <stdlib.h>
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <stdbool.h>
  49.  
  50. #include "wimplib.h"
  51. #include "kernel.h"
  52. #include "swis.h"
  53. #include "err.h"
  54. #include "msgtrans.h"
  55.  
  56. #define Wimp_ReportError_UseCategory (1u << 8)
  57.  
  58. #ifndef NO_RECORD_ERR
  59. static bool suppress_errors = false;
  60. static _kernel_oserror recorded_error;
  61. #endif
  62. static bool riscos_350 = false;
  63. static char err_taskname[32] = "application";
  64.  
  65. /* ----------------------------------------------------------------------- */
  66. /*                       Function prototypes                               */
  67.  
  68. static void fancy_error(_kernel_oserror *dest_block, const int errnum, const char *errmess, bool fatal);
  69. static void err_box_continue(_kernel_oserror *errblk);
  70.  
  71. /* ----------------------------------------------------------------------- */
  72. /*                         Public functions                                */
  73.  
  74. #ifndef NO_RECORD_ERR
  75. void err_suppress_errors(void)
  76. {
  77.   suppress_errors = true;
  78.   recorded_error.errnum = 255;
  79.   recorded_error.errmess[0] = '\0';
  80. }
  81.  
  82. /* ----------------------------------------------------------------------- */
  83.  
  84. _kernel_oserror *err_dump_suppressed(void)
  85. {
  86.   suppress_errors = false;
  87.   if(strcmp(recorded_error.errmess, "") == 0)
  88.     return NULL;
  89.   return &recorded_error;
  90. }
  91. #endif
  92.  
  93. /* ----------------------------------------------------------------------- */
  94.  
  95. void err_set_taskname(const char *name, bool new_errs)
  96. {
  97.   strncpy(err_taskname, name, sizeof(err_taskname)-1);
  98.   riscos_350 = new_errs;
  99. }
  100.  
  101. /* ----------------------------------------------------------------------- */
  102.  
  103. bool err_check(const _kernel_oserror *er)
  104. {
  105.   if(er == NULL) {
  106.     return false;
  107.   }
  108.   else {
  109.     err_check_rep(er);
  110.     return true;
  111.   }
  112. }
  113.  
  114. /* ----------------------------------------------------------------------- */
  115.  
  116. void err_check_rep(const _kernel_oserror *er)
  117. {
  118.  
  119. #ifndef NO_RECORD_ERR
  120.   /* Should we preserve the error for posterity? */
  121.   if(suppress_errors) {
  122.     suppress_errors = false;
  123.     recorded_error = *er;
  124.   }
  125.   else {
  126. #endif
  127.     _kernel_oserror erblk;
  128.     fancy_error(&erblk, er->errnum, er->errmess, false);
  129.     err_box_continue(&erblk);
  130. #ifndef NO_RECORD_ERR
  131.   }
  132. #endif
  133. }
  134.  
  135. /* ----------------------------------------------------------------------- */
  136.  
  137. void err_check_fatal_rep(const _kernel_oserror *er)
  138. {
  139.   _kernel_oserror erblk;
  140.   
  141.   fancy_error(&erblk, er->errnum, er->errmess, true);
  142.   err_box_die(&erblk);
  143. }
  144.  
  145. /* ----------------------------------------------------------------------- */
  146.  
  147. void err_report(int num, const char *mess)
  148. {
  149.  
  150. #ifndef NO_RECORD_ERR
  151.   /* Should we preserve the error for posterity? */
  152.   if(suppress_errors) {
  153.     suppress_errors = false;
  154.     recorded_error.errnum = num;
  155.     strncpy(recorded_error.errmess, mess, sizeof(recorded_error.errmess)-1);
  156.   }
  157.   else {
  158. #endif
  159.     _kernel_oserror erblk;
  160.     erblk.errnum = num;
  161.     strncpy(erblk.errmess, mess, sizeof(erblk.errmess)-1);
  162.     wimp_report_error(&erblk, Wimp_ReportError_OK, err_taskname);
  163. #ifndef NO_RECORD_ERR
  164.   }
  165. #endif
  166. }
  167.  
  168. /* ----------------------------------------------------------------------- */
  169.  
  170. void err_complain(int num, const char *mess)
  171. {
  172.   
  173. #ifndef NO_RECORD_ERR
  174.   /* Should we preserve the error for posterity? */
  175.   if(suppress_errors) {
  176.     suppress_errors = false;
  177.     recorded_error.errnum = num;
  178.     strncpy(recorded_error.errmess, mess, sizeof(recorded_error.errmess)-1);
  179.   }
  180.   else {
  181. #endif
  182.     _kernel_oserror erblk;
  183.     fancy_error(&erblk, num, mess, false);
  184.     err_box_continue(&erblk);
  185. #ifndef NO_RECORD_ERR
  186.   }
  187. #endif
  188. }
  189.  
  190. /* ----------------------------------------------------------------------- */
  191.  
  192. void err_complain_fatal(int num, const char *mess)
  193. {
  194.   _kernel_oserror erblk;
  195.   
  196.   fancy_error(&erblk, num, mess, true);
  197.   err_box_die(&erblk);
  198. }
  199.  
  200. /* ----------------------------------------------------------------------- */
  201. /*                         Private functions                               */
  202.  
  203. static void fancy_error(_kernel_oserror *dest_block, const int errnum, const char *errmess, bool fatal)
  204. {
  205.   char *token;
  206.  
  207.   if(fatal) {
  208.     token = "FatErr";
  209.   }
  210.   else {
  211.     if(riscos_350)
  212.       token = "NewErr";
  213.     else
  214.       token = "OldErr";
  215.   }
  216.   _kernel_oserror *lookup_err = _swix(MessageTrans_Lookup, _INR(0,4), msgs_get_descriptor(), token, dest_block->errmess, sizeof(dest_block->errmess), errmess);
  217.   if(lookup_err != NULL) {
  218.     wimp_report_error(lookup_err, Wimp_ReportError_Cancel, err_taskname);
  219.     exit(EXIT_FAILURE); /* Failure to find our messages is fatal! */
  220.   }
  221.   dest_block->errnum = errnum;
  222. }
  223.  
  224. /* ----------------------------------------------------------------------- */
  225.  
  226. static void err_box_continue(_kernel_oserror *errblk)
  227. {
  228.   if(riscos_350) {
  229.     /* Nice error box */
  230.     char err_buttons[32];
  231.     _kernel_oserror *lookup_err = _swix(MessageTrans_Lookup, _INR(0,3), msgs_get_descriptor(), "ErrButtons", err_buttons, sizeof(err_buttons));
  232.     if(lookup_err != NULL) {
  233.       /* Failure to find our messages is fatal! */
  234.       wimp_report_error(lookup_err, Wimp_ReportError_Cancel, err_taskname);
  235.     } else {
  236.       if(wimp_report_error(errblk, Wimp_ReportError_OK|Wimp_ReportError_UseCategory, err_taskname, NULL, NULL, err_buttons) == Wimp_ReportError_OK)
  237.         return; /* we live on */
  238.     }
  239.   } else {
  240.     /* Backwards compatibility */
  241.     if(wimp_report_error(errblk, Wimp_ReportError_OK|Wimp_ReportError_Cancel, err_taskname) == Wimp_ReportError_OK)
  242.       return; /* we live on */
  243.   }
  244.   exit(EXIT_FAILURE); /* die (message not found, or user quit) */
  245. }
  246.  
  247. /* ----------------------------------------------------------------------- */
  248.  
  249. void err_box_die(_kernel_oserror *errblk)
  250. {
  251.   if(riscos_350) {
  252.     /* Nice error box */
  253.     char err_buttons[32];
  254.     _kernel_oserror *lookup_err = _swix(MessageTrans_Lookup, _INR(0,3), msgs_get_descriptor(), "ErrButtons", err_buttons, sizeof(err_buttons));
  255.     if(lookup_err != NULL)
  256.       wimp_report_error(lookup_err, Wimp_ReportError_Cancel, err_taskname);
  257.     else
  258.       wimp_report_error(errblk, Wimp_ReportError_UseCategory, err_taskname, NULL, NULL, err_buttons);
  259.   }
  260.   else {
  261.     /* Backwards compatibility */
  262.     wimp_report_error(errblk, Wimp_ReportError_Cancel, err_taskname);
  263.   }
  264.   exit(EXIT_FAILURE);
  265. }
  266.